/*
 * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "hi_io.h"
#include "iot_errno.h"
#include "hi_adc.h"

float density, voltage;
int adcvalue;
#define COV_RATIO 0.03   
#define NO_DUST_VOLTAGE 230 
#define SYS_VOLTAGE 7200 

//递推平均滤波算法
double Filter(int m)
{
    static int flag_first = 0, _buff[10], sum;
    const int _buff_max = 10;
    int i;
    if (flag_first == 0)
    {
        flag_first = 1;
        for (i = 0, sum = 0; i < _buff_max; i++)
        {
            _buff[i] = m;
            sum += _buff[i];
        }
    }
    else
    {
        sum -= _buff[0];
        for (i = 0; i < (_buff_max - 1); i++)
        {
            _buff[i] = _buff[i + 1];
        }
        _buff[9] = m;
        sum += _buff[9];
    }
    return  sum/10.0;
}

/***** 获取电压值函数 *****/
unsigned int GetVoltage(void)
{
    unsigned int ret;
    unsigned short data;
    ret = hi_adc_read(HI_ADC_CHANNEL_2, &data, HI_ADC_EQU_MODEL_8, HI_ADC_CUR_BAIS_DEFAULT, 0xff);//adc读取
    if (ret != IOT_SUCCESS)
        printf("ADC Read Fail\n");//判断是否ADC读取成功
    return data;
}

double GetGP2Y(void)
{
    IoTGpioSetOutputVal(HI_IO_NAME_GPIO_7, 1);//设置GPIO_7为输出低电平
    usleep(280);
	adcvalue = GetVoltage();
    IoTGpioSetOutputVal(HI_IO_NAME_GPIO_7, 0);//设置GPIO_7为输出低电平
	adcvalue = Filter(adcvalue);
	voltage = (SYS_VOLTAGE / 4096.0) * adcvalue * 11;
	if(voltage >= NO_DUST_VOLTAGE)
    {
        voltage -= NO_DUST_VOLTAGE;
        density = voltage * COV_RATIO;
    }
    else
        density = 0;
    return density;
 }

static void adc_task(void)
{
    //初始化GPIO
    IoTGpioInit(HI_IO_NAME_GPIO_0);
    hi_io_set_func(HI_IO_NAME_GPIO_7, HI_IO_FUNC_GPIO_7_GPIO);//设置GPIO_7的复用功能为普通GPIO
    IoTGpioSetDir(HI_IO_NAME_GPIO_7, IOT_GPIO_DIR_OUT);    //设置GPIO_7为输出模式
    IoTGpioSetOutputVal(HI_IO_NAME_GPIO_7, 0);//设置GPIO_7为输出低电平
    while(1)
    {    
        printf("The current dust concentration is:%4.2fug/m3\n ",GetGP2Y());
        sleep(1);
    }
}

static void adc_pm2_5(void)
{
    osThreadAttr_t attr;
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024 * 4;

    attr.name = "adc_task";
    attr.priority = 25;
    if(osThreadNew((osThreadFunc_t)adc_task, NULL, &attr) == NULL)
    {
        printf("Falied to create adc_task!\n");
    }
}
APP_FEATURE_INIT(adc_pm2_5);